<?php

namespace app\common\service\trainer;


use app\common\enums\core\AuditStateEnum;
use app\common\enums\TimeApplyTypeEnum;
use app\common\enums\TrainerTimeStatusEnum;
use app\common\model\banxi\core\CoreTrainerTime;
use app\common\model\banxi\core\CoreTrainerTimeApply;
use app\common\model\banxi\trainer\Trainer;
use app\common\service\ApiService;
use ba\Exception;
use think\db\exception\PDOException;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Db;

class TrainerTimeApplyService extends ApiService
{
    public function audit(array $data)
    {
        Db::startTrans();
        try {
            $applyId = $data['applyId'];
            $coreTrainerTimeApply = new CoreTrainerTimeApply();
            $timeApply = $coreTrainerTimeApply->where(['id' => $applyId])->find();
            if (!$timeApply) {
                throw new ValidateException('申请记录不存在');
            }
            $auditState = $timeApply['auditState'];
            if ($auditState != AuditStateEnum::E1) {
                throw new ValidateException('该申请已被审核');
            }
            $result = $data['result'];
            $coreTrainerTimeApply->update([
                'auditState' => $result ? AuditStateEnum::E2 : AuditStateEnum::E3,
            ], [
                'id' => $applyId,
                'auditState' => $auditState
            ]);
            if ($result) {
                $trainerId = $timeApply['trainerId'];
                $trainer = Trainer::where(['id' => $trainerId])->find();
                if (!$trainer) {
                    throw new ValidateException('审核失败，教练不存在');
                }
                $coreTrainerTime = new CoreTrainerTime();
                $lock = $coreTrainerTime->lockTrainer($trainer);
                try {
                    $applyDate = $timeApply['applyDate'];
                    $applyStartTime = $timeApply['applyStartTime'];
                    $applyEndTime = $timeApply['applyEndTime'];
                    $applyType = $timeApply['applyType'];
                    $dateList = [$applyDate];
                    $trainerTimeList = $coreTrainerTime->listNotIdleByTrainerAndDateIn($trainerId, $dateList);
                    $timeApplyTypeEnum = new TimeApplyTypeEnum();
                    $status = $timeApplyTypeEnum->getTrainerTimeStatus($applyType);
                    $trainerTimeList[] = [
                        'trainerId' => $trainerId,
                        'date' => $applyDate,
                        'startTime' => $applyStartTime,
                        'endTime' => $applyEndTime,
                        'status' => $status
                    ];
                    $trainerTimeNewList = $coreTrainerTime->getPlanTimeIdle($trainerTimeList);
                    if (!empty($trainerTimeNewList)) {
                        $insertData = array_filter($trainerTimeNewList, function ($item) {
                            return !isset($item['id']);
                        });
                        // 过滤出需要更新的数据（id 不为空）
                        $updateData = array_filter($trainerTimeNewList, function ($item) {
                            return isset($item['id']);
                        });
                        $coreTrainerTime->removeByIdleAndTrainerAndDateIn([$trainerId], $dateList);
                        if (!empty($insertData)) {
                            $coreTrainerTime->saveAll($insertData);
                        }
                        if (!empty($updateData)) {
                            foreach ($updateData as $item) {
                                $coreTrainerTime->update($item, ['id' => $item['id']]);
                            }
                        }
                    }
                } catch (Exception|PDOException|ValidateException $e) {
                    throw new ValidateException($e->getMessage());
                } finally {
                    Cache::delete($lock);
                }

            }
            Db::commit();
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
        return true;


    }

    public function shiftScheduling($time)
    {
        Db::startTrans();
        try {
            $trainerId = $time['trainerId'];
            $trainer = Trainer::where(['id' => $trainerId])->find();
            if (!$trainer) {
                throw new ValidateException('添加失败，教练不存在');
            }

            $applyDate = $time['applyDate'];
            $applyStartTime = $time['applyStartTime'];
            $applyEndTime = $time['applyEndTime'];
            $applyType = $time['applyType'];
            $coreTrainerTimeApply = new CoreTrainerTimeApply();
            $coreTrainerTimeApply->save([
                'trainerId' => $trainerId,
                'applyDate' => $applyDate,
                'applyStartTime' => $applyStartTime,
                'applyEndTime' => $applyEndTime,
                'applyType' => $applyType,
                'auditState' => AuditStateEnum::E2
            ]);
            $dateNow = date('Y-m-d'); //当前日期
            $dateTimeNow = strtotime(date('Y-m-d H:i:s')); // 当前时间戳
            if (strtotime($applyDate) < strtotime($dateNow)) {
                throw new ValidateException(sprintf('日期不能小于今天 %s', $applyDate));
            }
            $dateTime = strtotime("{$applyDate} {$applyStartTime}");
            if ($dateTime < $dateTimeNow) {
                throw new ValidateException("时间不能低于现在 {$applyDate} {$applyStartTime}");
            }

            $coreTrainerTime = new CoreTrainerTime();
            $lock = $coreTrainerTime->lockTrainer($trainer);
            try {
                $dateList = [$applyDate];
                $trainerTimeList = $coreTrainerTime->listNotIdleByTrainerAndDateIn($trainerId, $dateList);
                $timeApplyTypeEnum = new TimeApplyTypeEnum();
                $status = $timeApplyTypeEnum->getTrainerTimeStatus($applyType);
                $trainerTimeList[] = [
                    'trainerId' => $trainerId,
                    'date' => $applyDate,
                    'startTime' => $applyStartTime,
                    'endTime' => $applyEndTime,
                    'status' => $status
                ];
                $trainerTimeNewList = $coreTrainerTime->getPlanTimeIdle($trainerTimeList);
                if (!empty($trainerTimeNewList)) {
                    $insertData = array_filter($trainerTimeNewList, function ($item) {
                        return !isset($item['id']);
                    });
                    // 过滤出需要更新的数据（id 不为空）
                    $updateData = array_filter($trainerTimeNewList, function ($item) {
                        return isset($item['id']);
                    });
                    $coreTrainerTime->removeByIdleAndTrainerAndDateIn([$trainerId], $dateList);
                    if (!empty($insertData)) {
                        $coreTrainerTime->saveAll($insertData);
                    }
                    if (!empty($updateData)) {
                        foreach ($updateData as $item) {
                            $coreTrainerTime->update($item, ['id' => $item['id']]);
                        }
                    }
                }
            } catch (Exception|PDOException|ValidateException $e) {
                throw new ValidateException($e->getMessage());
            } finally {
                Cache::delete($lock);
            }
            Db::commit();
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
        return true;
    }

    public function shiftSchedulingCalendar($trainerId, $year, $month)
    {
        $daysInMonth = date('t', mktime(0, 0, 0, $month, 1, $year));

        // 创建一个包含所有天数的数组
        $daysArray = range(1, $daysInMonth);
        $coreTrainerTimeModel = new CoreTrainerTime();
        $timeStatusList = $coreTrainerTimeModel->where([
            ['date', 'between', [$year . '-' . $month . '-01', $year . '-' . $month . '-' . $daysInMonth]],
            ['trainerId', '=', $trainerId]
        ])->order(['startTime' => 'asc'])->select()->toArray();
        $groupedTimeStatus = array_reduce($timeStatusList, function ($carry, $item) {
            $date = $item['date'];
            $carry[$date][] = $item;
            return $carry;
        }, []);
        $calendar = [];
        foreach ($daysArray as $day) {
            $date = date('Y-m-d', mktime(0, 0, 0, $month, $day, $year));
            $calendar[] = [
                'date' => $date,
                'list' => $groupedTimeStatus[$date] ?? [
                        'status' => 3,
                        'statusCn' => (new TrainerTimeStatusEnum())->getDescription(3) ?? ''
                    ]
            ];
        }
        return $calendar;
    }
}